package drawing;

import ij.IJ;
import ij.ImagePlus;
import ij.process.ImageProcessor;

import java.awt.Color;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.List;

import ownclasses.Eigensolver2x2;
import ownclasses.Eigensolver2x2.EigenPair;

import excaptions.AandBZeroException;

public class AlgebraicLine {

	public double m_A;
	public double m_B;
	public double m_C;
	private double m_DrawThreshhold = 0.5;
	private double m_IntersectThreshhold = 1.0;
	
	public AlgebraicLine(double A, double B, double C)
	throws AandBZeroException
	{
		if(A == 0.0 && B == 0.0)
		{
			throw new AandBZeroException();
		}
		m_A = A;
		m_B = B;
		m_C = C;
	}
	
	public AlgebraicLine(Point2D P1, Point2D P2) throws AandBZeroException
	{		
		double k = (P2.getY()-P1.getY())/(P2.getX()-P1.getX());
		double n = P1.getY() - k*P1.getX();
		m_A = -k;
		m_C = -n;
		m_B = 1;
		if(m_A == 0.0 && m_B == 0.0)
		{
			throw new AandBZeroException();
		}
	}
	
	public AlgebraicLine(List<Point> points)
	{
		double x = 0;
		double xx = 0;
		double y = 0;
		double yy = 0;
		double xy = 0;
		for(int i = 0; i < points.size(); i++)
		{
			Point a = points.get(i);
			//IJ.log("X: " + a.getX()+" Y: "+a.getY());
			x += a.getX();
			y += a.getY();
			xx += (a.getX() * a.getX());
			yy += (a.getY() * a.getY());
			xy += (a.getX() * a.getY());
		}
		x = x/points.size();
		y = y/points.size();
		xx = xx/points.size();
		yy = yy/points.size();
		xy = xy/points.size();
		
		double alpha = xx - (x*x);
		double beta = xy-x*y;
		double gamma = yy-(y*y);
//		IJ.log("a: " + alpha + " | " + beta + " | "+gamma);
		EigenPair[] e = Eigensolver2x2.realEigenValues2x2(alpha, beta, beta, gamma);
		double theta = e[1].getEigenvalue();
		double A = e[1].getEigenvector()[0];
		double B = e[1].getEigenvector()[1];
		if(e[0].getEigenvalue() < e[1].getEigenvalue())
		{
			theta = e[0].getEigenvalue();
			A = e[0].getEigenvector()[0];
			B = e[0].getEigenvector()[1];
		} else 
		{
			theta = e[1].getEigenvalue();
			A = e[1].getEigenvector()[0];
			B = e[1].getEigenvector()[1];
		}
		double C = 0 - (x * A) - (y * B);
		//IJ.log("A: " + A+" B: "+B+" C: "+C);
		
		m_A = A;
		m_B = B;
		m_C = C;
		this.normalize();
			
		
		
	}
	
	public ImageProcessor draw(ImageProcessor ip, Color col)
	{
		//IJ.log(" " +ip.getHeight());
		ip.setColor(col);
		for(int j = 0; j < ip.getHeight(); j++)
		{
			for(int i = 0; i < ip.getWidth(); i++)
			{
				if(m_A * i + m_B * j + m_C < m_DrawThreshhold && m_A * i + m_B * j + m_C > -m_DrawThreshhold)
				{
					ip.drawPixel(i, j);
				}
			}
		}
		return ip;
	}
	
	public void normalize()
	{
		double n = 1 / (Math.sqrt(m_A * m_A + m_B * m_B));
		m_A = m_A * n;
		m_B = m_B * n;
		m_C = m_C * n;
	}
	
	public double distance(Point2D x) 
	{
		double d = Math.abs((m_A*x.getX() + m_B*x.getY() + m_C)/(Math.sqrt(m_A*m_A + m_B*m_B)));
		return d;
	}

	public Point intersect(AlgebraicLine L2)
	{
//		IJ.log("Abweichung: "+(m_A*L2.m_B - L2.m_A*m_B));
		if((m_A*L2.m_B - L2.m_A*m_B) >= -m_IntersectThreshhold && (m_A*L2.m_B - L2.m_A*m_B) <= m_IntersectThreshhold)
		{
			double x = (m_B*L2.m_C - L2.m_B*m_C)/(m_A*L2.m_B - L2.m_A*m_B);
			double y = (m_C*L2.m_A - L2.m_C*m_A)/(m_A*L2.m_B - L2.m_A*m_B);
			return new Point((int)x, (int)y);
		}
		return null; 
	}
	
	
	
	
}
